#ifndef RP2SHADER_H
#define RP2SHADER_H

#include "Rp2Object.h"
#include "Rp2Program.h"
#include "Rp2Texture.h"

namespace Rp2
{

class Shader : public Object
{
	RP2_DECLARE_RTTI;
	RP2_DECLARE_NAME_ID;

public:
	Shader();
	// abstract base class
	virtual ~Shader();

    // The name of the shader object.  The program object has a name that
    // contains the shader name as a substring, but adds additional text
    // as needed (the path to a shader on disk, the identifying information
    // for a procedurally generated shader).
    const std::string& GetShaderName () const;

    // Get the number of Texture objects used by the Shader.
    int GetTextureQuantity () const;

    // Returns 'true' when 0 <= i < GetTextureQuantity() and the Texture
    // object is not null.  The non-null requirement is based on your knowing
    // that the shader program indeed requires a texture that it will sample.
    bool SetTexture (int i, Texture* pkTexture);

    // Returns 'true' when 0 <= i < GetTextureQuantity() and a Texture object
    // by the specified name exists in the active Catalog<Texture>.
    bool SetTexture (int i, const std::string& rkName);	

    // Returns a non-null Texture object when 0 <= i < GetTextureQuantity().
    Texture* GetTexture (int i);
    const Texture* GetTexture (int i) const;

    // Returns a non-null Texture when the specified name corresponds to a
    // Texture object stored by the Shader.
    Texture* GetTexture (const std::string& rkName);
    const Texture* GetTexture (const std::string& rkName) const;

	Shader(GLint uiNumVerts);
	
	// Create shader program
	GLuint CreateProgram(char* acVertexShader, char* acPixelShader, ...);
	// Load shader from desk
	bool LoadShader(const char* acFileName, GLuint uiShader);


	void BindBuffers(GLenum eAttribute, GLfloat* pfBuffer);

	// Member access
	GLuint GetVShader();
	GLuint GetPShader();

protected:


    // The constructor called by the derived classes VertexShader and
    // PixelShader.
    Shader (const std::string& rkShaderName);

    // The VertexShader and PixelShader constructors must access their
    // respective catalogs to load programs.  After a program is loaded,
    // the user constants must be hooked up to their data sources and
    // the number of textures the samplers use must be set.  This function
    // does this work.
    void OnLoadProgram ();

    // The shader name, which contributes to a uniquely identifying string
    // for a shader program.
    std::string m_kShaderName;

    // The shader program, which is dependent on graphics API.
    ProgramPtr m_spkProgram;

    // The user-defined data are specific to each shader object.  The Program
    // object knows only the name, which register to assign the value to, and
    // how many registers to use.  The storage provided here is for the
    // convenience of Shader-derived classes.  However, a derived class may
    // provide alternate storage by calling UserConstant::SetDataSource for
    // each user constant of interest.
    std::vector<float> m_kUserData;

    // The Texture objects used by the samplers.
    std::vector<TexturePtr> m_kTextures;

	// Shader object
	GLchar m_acVertexShader[RP2_MAX_FILENAME_LENGTH];
	GLchar m_acPixelShader[RP2_MAX_FILENAME_LENGTH];
	GLuint m_uiVertexShader;
	GLuint m_uiPixelShader;

	// Shader program
	GLuint m_uiProgram;
	
	// Buffer support
	GLuint m_uiNumVerts;
	
	// Storage of shader file
	char* m_acShaderText;
};

typedef Pointer<Shader> ShaderPtr;
#include "Rp2Shader.inl"

}

#endif